package
{
	import com.adobe.images.JPGEncoder;
	import com.quasimondo.bitmapdata.CameraBitmap;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Graphics;
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Matrix;
	import flash.geom.Rectangle;
	import flash.net.SharedObject;
	import flash.utils.ByteArray;
	
	import jp.maaash.ObjectDetection.ObjectDetector;
	import jp.maaash.ObjectDetection.ObjectDetectorEvent;
	import jp.maaash.ObjectDetection.ObjectDetectorOptions;
	
	import mx.containers.Canvas;
	import mx.core.UIComponent;
	
	public class FaceDetector extends Canvas
	{
		
		public var detector    :ObjectDetector;
		public var options     :ObjectDetectorOptions;	
		public var view :Sprite;
		public var faceRectContainer :Sprite;
		public var camera:CameraBitmap;
		public var detectionMap:BitmapData;
		public var drawMatrix:Matrix;
		public var scaleFactor:int = 4;
		public var w:int = 375;
		public var h:int = 175;
		public var detectedFace:BitmapData;
		public var detectedRect:Rectangle = null;		
		public var So:SharedObject= SharedObject.getLocal("TempImage");
		[Bindable]
		public var ba:ByteArray;
		[Bindable]
		public var spriteContainer:UIComponent;
		[Bindable]
		public var enable:Boolean=false;
		[Bindable]
		public var bmp:Bitmap=null;
		
		public function FaceDetector()
		{
			init();
			initDetector();
		}
		
		public function init():void{
			
			view = new Sprite();
			camera = new CameraBitmap( w, h, 15 );
			camera.addEventListener( Event.RENDER, cameraReadyHandler );
			view.addChild( new Bitmap( camera.bitmapData ) );
			
			detectionMap = new BitmapData( w / scaleFactor, h / scaleFactor, false, 0 );
			drawMatrix = new Matrix( 1/ scaleFactor, 0, 0, 1 / scaleFactor );
			
			faceRectContainer = new Sprite();
			view.addChild( faceRectContainer);
			
			spriteContainer= new UIComponent();
			spriteContainer.addChild(view);
			
		}
		
		public function cameraReadyHandler( event:Event ):void
		{
			detectionMap.draw(camera.bitmapData,drawMatrix,null,"normal",null,true);
			detector.detect( detectionMap );
		}
		
		public function initDetector():void
		{
			detector = new ObjectDetector();
			
			var options:ObjectDetectorOptions = new ObjectDetectorOptions();
			options.min_size  = 30;
			detector.options = options;
			detector.addEventListener(ObjectDetectorEvent.DETECTION_COMPLETE, detectionHandler );
		}
		
		
		public function detectionHandler( e :ObjectDetectorEvent ):void
		{
			var g :Graphics = faceRectContainer.graphics;
			g.clear();
			if( e.rects ){
				g.lineStyle( 2 );	// black 2pix
				e.rects.forEach( function( r :Rectangle, idx :int, arr :Array ) :void {
					
					g.drawRect( r.x * scaleFactor, r.y * scaleFactor, r.width * scaleFactor, r.height * scaleFactor );						
					detectedRect = r;
					enable=true;
				});
			}else{
				detectedRect = null;
				enable=false;
			}
		}
		
		public function displayImage(event:Event):void {
			
			bmp= event.currentTarget.content as Bitmap;
			bmp.smoothing=true;
		}
		
		
		public function loadImage(imgSo:ByteArray):void{
			var imgLoader:Loader = new Loader();
			imgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,displayImage);
			imgLoader.loadBytes(imgSo);
		}
		
		private function saveImage():void {
			
			So.data.image = ba;
			try {
				So.flush();
			} catch (error:Error) {
				trace("Error...Could not write SharedObject to disk\n");
			}
			
			loadImage(So.data.image);
			
		}
		
		public function extractFace( ):void
		{	
			var encoder:JPGEncoder = new JPGEncoder();
			
			var detectedByte:ByteArray = detectionMap.getPixels(detectedRect);
			detectedByte.position = 0;
			
			detectedFace = new BitmapData( detectedRect.width, detectedRect.height, true );
			
			for( var i:uint=0; i<detectedRect.height ; i++ )
			{
				for( var j:uint=0; j<detectedRect.width; j++ )
				{
					detectedFace.setPixel( j, i, detectedByte.readUnsignedInt() );
				}
			}
			
			ba= encoder.encode(detectedFace);
			ba.position=0;
			saveImage();
			
		}
		
	}
}